/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package alogic;

import aentity.aeArco;
import aentity.aePuntoUbicacion;
import bentity.beAlmacen;
import bentity.beUbicacion;
import blogic.blHelper;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;

/**
 *
 * @author renzo
 */
public class alAlgMetaHeu {
    public int distanciaTotal = 0;
    public Point entrada = new Point(0,0);
    public ArrayList<aePuntoUbicacion> obligatorios = new ArrayList<aePuntoUbicacion>();
    public ArrayList<aePuntoUbicacion> transitorios = new ArrayList<aePuntoUbicacion>();
    public char[][] matriz;
    public int[][] distNodos;
    public int[][] matrizArcos;
    public int tamanhoLado = 0;
    public int tamanhoLadoArco = 0;

    private int[][][] transitoriosUtil;
    private ArrayList<aePuntoUbicacion> puntosRutaOptima = new ArrayList<aePuntoUbicacion>();
    private ArrayList<beUbicacion> ordenOptimoUbics = new ArrayList<beUbicacion>();

    public static final double ALFA = 0.99;
    public static final double T_INICIAL = 20.0;
    public static final double E = 0.01;
    public static final int K = 2*60*60;

    public alAlgMetaHeu(){

    }

    public void CalcularRutaOptima(ArrayList<beUbicacion> ubicaciones) throws Exception{
        this.ubicarNodosObligatorios(ubicaciones);
        this.ubicarNodosTransitorios(ubicaciones.get(0).getCoordenadas().getxEnMapa(),ubicaciones.get(0).getCoordenadas().getyEnMapa());
        this.calcularMatrizNodos();
        this.LlenarMatrizDistanciasNodos(this.obligatorios);
        this.RecocidoSimulado(this.obligatorios);
        this.armarOrdenOptimoUbics(ubicaciones);
        this.incluirNodosTransitorios();
        System.out.println("RUTA CON PUNTOS TRANSITORIOS");
        for(int i=0;i<this.puntosRutaOptima.size();i++){
            if (this.puntosRutaOptima.get(i).getIdUbicacion() != -1)
                System.out.println(i+")\t"+this.puntosRutaOptima.get(i).getIdUbicacion());
            else
                System.out.println(i+")\tPto. de paso con orden "+this.puntosRutaOptima.get(i).getOrden());
        }
        System.out.println("RUTA SIN PUNTOS TRANSITORIOS");
        for(int i=0;i<this.ordenOptimoUbics.size();i++)
            System.out.println(i+")\t"+this.ordenOptimoUbics.get(i).getIdUbicacion());
    }

    private void incluirNodosTransitorios() {
        ArrayList<aePuntoUbicacion> listaAux = new ArrayList<aePuntoUbicacion>();
        aePuntoUbicacion pto = null;
        int orden1 = -1;
        int orden2 = -1;
        for(int i=0; i<this.puntosRutaOptima.size(); i++){
            if (i==(this.puntosRutaOptima.size()-1)){
                orden1 = this.puntosRutaOptima.get(i).getOrden();
                orden2 = this.puntosRutaOptima.get(0).getOrden();
            }
            else{
                orden1 = this.puntosRutaOptima.get(i).getOrden();
                orden2 = this.puntosRutaOptima.get(i+1).getOrden();
            }
            if (i==0)
                listaAux.add(this.puntosRutaOptima.get(i));
            for(int j=0; this.transitoriosUtil[orden1][orden2][j]!=-1;j++){
                if ((this.transitoriosUtil[orden1][orden2][j]!=orden1)&&(this.transitoriosUtil[orden1][orden2][j]!=orden2)){
                    pto = new aePuntoUbicacion();
                    pto = this.obtenerTransitorioPorOrden(this.transitoriosUtil[orden1][orden2][j]);
                    if (pto != null){
                        pto.setIdUbicacion(-1);
                        listaAux.add(pto);
                    }
                }
            }
            if (i==(this.puntosRutaOptima.size()-1))
                listaAux.add(this.puntosRutaOptima.get(0));
            else
                listaAux.add(this.puntosRutaOptima.get(i+1));
        }
        this.puntosRutaOptima = this.CopiarLista(listaAux);
    }

    private aePuntoUbicacion obtenerTransitorioPorOrden(int ordenTransitorio) {
        for(int i=0; i<this.transitorios.size(); i++){
            if (this.transitorios.get(i).getOrden() == ordenTransitorio)
                return this.transitorios.get(i);
        }
        return null;
    }

    private void armarOrdenOptimoUbics(ArrayList<beUbicacion> ubicaciones){
        beUbicacion u = null;
        for(int i=0; i<this.puntosRutaOptima.size(); i++){
            u = this.obtenerUbicacionPorId(ubicaciones, this.puntosRutaOptima.get(i).getIdUbicacion());
            this.ordenOptimoUbics.add(u);
        }
    }

    private beUbicacion obtenerUbicacionPorId(ArrayList<beUbicacion> ubicaciones, int idUbicacion){
        for(int i=0; i<ubicaciones.size(); i++){
            if (ubicaciones.get(i).getIdUbicacion() == idUbicacion)
                return ubicaciones.get(i);
        }
        return null;
    }

    private void RecocidoSimulado(ArrayList<aePuntoUbicacion> obligatorios) {
        ArrayList<aePuntoUbicacion> solucionActual = CopiarLista(obligatorios);
        ArrayList<aePuntoUbicacion> solucionMenor = CopiarLista(solucionActual);
        ArrayList<aePuntoUbicacion> solucionSiguiente = null;
        int distanciaActual = 0;
        int distanciaMenor = 0;
        int distanciaSiguiente = 0;
        double delta = 0.0;
        double prob = 0.0;
        Random rnd = new Random();
        distanciaActual = ObtenerDistanciaSolucionActual(solucionActual);
        distanciaMenor = distanciaActual;
        distanciaSiguiente = distanciaMenor;
        ImprimirSolucion(solucionMenor);
        for(double tActual = this.T_INICIAL; tActual>this.E; tActual = this.ALFA*tActual){
            for(int i=0; i<this.K; i++){
                solucionSiguiente = PermutacionAleatoria(solucionActual);
                distanciaSiguiente = ObtenerDistanciaSolucionActual(solucionSiguiente);
                delta = distanciaSiguiente - distanciaActual;
                if (delta<0){
                    solucionActual = CopiarLista(solucionSiguiente);
                    solucionMenor = CopiarLista(solucionSiguiente);
                    distanciaActual = distanciaSiguiente;
                    distanciaMenor = distanciaSiguiente;
                }
                else{
                    prob = rnd.nextDouble();
                    if(prob< Math.exp(-delta/tActual)){
                        solucionActual = CopiarLista(solucionSiguiente);
                        distanciaActual = distanciaSiguiente;
                    }
                }
            }
            distanciaActual = distanciaMenor;
            solucionActual = CopiarLista(solucionMenor);
        }
        this.puntosRutaOptima = CopiarLista(solucionMenor);
        this.distanciaTotal = distanciaActual;
        ImprimirSolucion(solucionMenor);
    }

    private void ImprimirSolucion(ArrayList<aePuntoUbicacion> solucion){
        int distancia = ObtenerDistanciaSolucionActual(solucion);
        for(int i=0; i<solucion.size(); i++){
            System.out.println(i+") "+solucion.get(i).getIdUbicacion());
            if (i==(solucion.size()-1))
                System.out.println((i+1)+")"+solucion.get(0).getIdUbicacion());
        }
        System.out.println("Distancia recorrida: "+distancia);
    }

    private int ObtenerDistanciaSolucionActual(ArrayList<aePuntoUbicacion> solucionActual){
        int distancia = 0;
        int org = -1;
        int fin = -1;
        for(int i=0; i<(solucionActual.size()-1); i++){
            org = solucionActual.get(i).getOrden();
            fin = solucionActual.get(i+1).getOrden();
            distancia += this.distNodos[org][fin];
        }
        org = solucionActual.get(solucionActual.size()-1).getOrden();
        fin = solucionActual.get(0).getOrden();
        distancia += this.distNodos[org][fin];
        return distancia;
    }

    private ArrayList<aePuntoUbicacion> PermutacionAleatoria(ArrayList<aePuntoUbicacion> lista){
        ArrayList<aePuntoUbicacion> nuevaLista = CopiarLista(lista);
        if (lista.size() > 2){
            Random rnd = new Random();
            int i1 = -1;
            int i2 = -1;
            aePuntoUbicacion pAux1 = null;
            aePuntoUbicacion pAux2 = null;
            if (lista.size() >= 10){
                for(;i1==i2;){
                    i1 = rnd.nextInt(lista.size()-1)+1;
                    i2 = rnd.nextInt(lista.size()-1)+1;
                }
            }
            else{
                for(int i=0;i1==i2;i++){
                    i1 = rnd.nextInt(lista.size()-1)+1;
                    i2 = rnd.nextInt(lista.size()-1)+1;
                    if (i==500){
                        i1 = lista.size()-1;
                        i2 = lista.size()-2;
                    }
                }
            }
            pAux1 = new aePuntoUbicacion();
            pAux1.setIdUbicacion(lista.get(i1).getIdUbicacion());
            pAux1.setOrden(lista.get(i1).getOrden());
            pAux1.setCoorX(lista.get(i1).x);
            pAux1.setCoorY(lista.get(i1).y);

            pAux2 = new aePuntoUbicacion();
            pAux2.setIdUbicacion(lista.get(i2).getIdUbicacion());
            pAux2.setOrden(lista.get(i2).getOrden());
            pAux2.setCoorX(lista.get(i2).x);
            pAux2.setCoorY(lista.get(i2).y);

            nuevaLista.get(i1).setIdUbicacion(pAux2.getIdUbicacion());
            nuevaLista.get(i1).setOrden(pAux2.getOrden());
            nuevaLista.get(i1).setCoorX(pAux2.getCoorX());
            nuevaLista.get(i1).setCoorY(pAux2.getCoorY());

            nuevaLista.get(i2).setIdUbicacion(pAux1.getIdUbicacion());
            nuevaLista.get(i2).setOrden(pAux1.getOrden());
            nuevaLista.get(i2).setCoorX(pAux1.getCoorX());
            nuevaLista.get(i2).setCoorY(pAux1.getCoorY());
        }
        return nuevaLista;
    }

    private ArrayList<aePuntoUbicacion> CopiarLista(ArrayList<aePuntoUbicacion> lista){
        ArrayList<aePuntoUbicacion> listaCopia = new ArrayList<aePuntoUbicacion>();
        aePuntoUbicacion pto = null;
        for(int i=0; i<lista.size(); i++){
            pto = new aePuntoUbicacion();
            pto.setIdUbicacion(lista.get(i).getIdUbicacion());
            pto.setCoorX(lista.get(i).getCoorX());
            pto.setCoorY(lista.get(i).getCoorY());
            pto.setOrden(lista.get(i).getOrden());
            listaCopia.add(pto);
        }
        return listaCopia;
    }

    private void LlenarMatrizDistanciasNodos(ArrayList<aePuntoUbicacion> obligatorios) {
        ArmarMatrizDistanciasNodos(obligatorios);
        MostrarMatrizDistanciasNodos();
        CalcularDistanciasNodos();
        MostrarMatrizDistanciasNodos();
    }

    private void ArmarMatrizDistanciasNodos(ArrayList<aePuntoUbicacion> obligatorios) {
        this.tamanhoLado = obligatorios.size();
        this.distNodos = new int [this.tamanhoLado][this.tamanhoLado];

        for(int fil=(this.tamanhoLado-1); fil>=0; fil--){
            for(int col=0; col<(this.tamanhoLado-fil); col++)
                if (col==(this.tamanhoLado-fil-1))
                    this.distNodos[col][this.tamanhoLado-fil-1]=-1;
        }
    }

    private void MostrarMatrizDistanciasNodos() {
//        for(int fil=0; fil<tamanhoLado; fil++){
//            for(int col=0; col<tamanhoLado; col++){
//                System.out.print(""+distNodos[col][fil]+"\t");
//            }
//            System.out.println("");
//        }
    }

    private void CalcularDistanciasNodos() {
        this.transitoriosUtil = new int[this.tamanhoLado][this.tamanhoLado][];
        for(int fil=(tamanhoLado-1); fil>=0; fil--){
            for(int col=0; col<(tamanhoLado-fil); col++){
                if (col!=(tamanhoLado-fil-1)){
                    //System.out.println("Distancia arco: ("+col+";"+(tamanhoLado-fil-1)+")");
                    distNodos[col][tamanhoLado-fil-1] = CalcularDistanciaDosNodos(col,(tamanhoLado-fil-1));
                    distNodos[tamanhoLado-fil-1][col] = distNodos[col][tamanhoLado-fil-1];
                }
            }
        }
    }

    private int CalcularDistanciaDosNodos(int ptoOrg, int ptoFin) {
        int current = -1;
        int distancia = 0;
        ArrayList<aeArco> marcadosFijos = new ArrayList<aeArco>();
        ArrayList<aeArco> marcadosTemps = new ArrayList<aeArco>();
        marcadosFijos.add(new aeArco(ptoOrg,-1,0));
        AgregarNuevosTemps(marcadosTemps, marcadosFijos, ptoOrg);
        ImprimirListas(marcadosFijos,marcadosTemps);
        for(;marcadosFijos.size() != this.tamanhoLadoArco;){
            current = MarcarMenorAgregarFijo(marcadosTemps, marcadosFijos);
            AgregarNuevosTemps(marcadosTemps, marcadosFijos, current);
//            ImprimirListas(marcadosFijos,marcadosTemps);
        }
//        ImprimirListas(marcadosFijos,marcadosTemps);
        distancia = ObtenerDistanciaMasCorta(marcadosFijos, ptoOrg, ptoFin);
        return distancia;
    }

    private int ObtenerDistanciaMasCorta(ArrayList<aeArco> marcadosFijos, int ptoOrg, int ptoFin) {
        int ptoCurrent = ptoFin;
        aeArco arcoCurrent = null;
//        System.out.println("Ruta");
        ArrayList<Integer> puntosDePaso = new ArrayList<Integer>();
        for( ; ptoCurrent != -1; ){
            arcoCurrent = ObtenerArco(marcadosFijos, ptoCurrent);
//            System.out.println("("+arcoCurrent.x+";"+arcoCurrent.y+";"+arcoCurrent.distancia+")");
            puntosDePaso.add(arcoCurrent.x);
            ptoCurrent = arcoCurrent.y;
        }
        this.transitoriosUtil[ptoOrg][ptoFin] = new int[puntosDePaso.size()+1];
        this.transitoriosUtil[ptoFin][ptoOrg] = new int[puntosDePaso.size()+1];
        for(int i=0; i<puntosDePaso.size(); i++)
            this.transitoriosUtil[ptoFin][ptoOrg][i] = puntosDePaso.get(i);
        for(int i=(puntosDePaso.size()-1); i>=0; i--)
            this.transitoriosUtil[ptoOrg][ptoFin][(puntosDePaso.size()-1)-i] = puntosDePaso.get(i);
        this.transitoriosUtil[ptoOrg][ptoFin][puntosDePaso.size()]=-1;
        this.transitoriosUtil[ptoFin][ptoOrg][puntosDePaso.size()]=-1;
        return ObtenerArco(marcadosFijos,ptoFin).getDistancia();
    }

    private aeArco ObtenerArco(ArrayList<aeArco> marcadosFijos, int ptoCurrent) {
        for(int i=0; i<marcadosFijos.size(); i++){
            if (marcadosFijos.get(i).x == ptoCurrent)
                return new aeArco(marcadosFijos.get(i).x, marcadosFijos.get(i).y, marcadosFijos.get(i).getDistancia());
        }
        return null;
    }

    private void ImprimirListas(ArrayList<aeArco> marcadosFijos, ArrayList<aeArco> marcadosTemps){
//        System.out.println("Fijos");
//        for(int i=0; i<marcadosFijos.size(); i++)
//            System.out.println("("+marcadosFijos.get(i).x+";"+marcadosFijos.get(i).y+";"+marcadosFijos.get(i).getDistancia()+")");
//        System.out.println("Temporales");
//        for(int i=0; i<marcadosTemps.size(); i++)
//            System.out.println("("+marcadosTemps.get(i).x+";"+marcadosTemps.get(i).y+";"+marcadosTemps.get(i).getDistancia()+")");
    }

    private int MarcarMenorAgregarFijo(ArrayList<aeArco> marcadosTemps, ArrayList<aeArco> marcadosFijos) {
        int distMenor = Integer.MAX_VALUE;
        int ptoMenor = 0;
        int ptoAntMenor = 0;
        int indiceMenor = 0;
        for(int i=0; i<marcadosTemps.size(); i++){
            if (marcadosTemps.get(i).getDistancia()<distMenor){
                distMenor = marcadosTemps.get(i).getDistancia();
                ptoMenor = marcadosTemps.get(i).x;
                ptoAntMenor = marcadosTemps.get(i).y;
                indiceMenor = i;
            }
        }
        marcadosTemps.remove(indiceMenor);
        marcadosFijos.add(new aeArco(ptoMenor,ptoAntMenor,distMenor));
        return ptoMenor;
    }

    private void AgregarNuevosTemps(ArrayList<aeArco> marcadosTemps, ArrayList<aeArco> marcadosFijos, int pto) {
        int [] arcosDelPto = this.matrizArcos[pto];
        int distancia = 0;
        for(int i=0; i<this.tamanhoLadoArco; i++){
            if ((arcosDelPto[i] != -1)&&(!EstaEnLista(marcadosFijos, i))){
                distancia = arcosDelPto[i]+ObtenerDistancia(marcadosFijos, pto);
                if (EstaEnLista(marcadosTemps, i)){
                    if (distancia<ObtenerPunto(marcadosTemps, i).getDistancia()){
                        RemoverPunto(marcadosTemps, i);
                        marcadosTemps.add(new aeArco(i, pto, distancia));
                    }
                }
                else
                    marcadosTemps.add(new aeArco(i, pto, distancia));
            }
        }
    }

    private void RemoverPunto(ArrayList<aeArco> lista, int pto){
        for(int i=0; i<lista.size(); i++){
            if (lista.get(i).x == pto)
                lista.remove(i);
        }
    }

    private aeArco ObtenerPunto(ArrayList<aeArco> lista, int pto) {
        for(int i=0; i<lista.size(); i++){
            if (lista.get(i).x == pto)
                return new aeArco(lista.get(i).x, lista.get(i).y, lista.get(i).getDistancia());
        }
        return null;
    }

    private int ObtenerDistancia(ArrayList<aeArco> marcadosFijos, int pto){
        for(int i=0; i<marcadosFijos.size(); i++){
            if (marcadosFijos.get(i).x == pto)
                return marcadosFijos.get(i).getDistancia();
        }
        return -1;
    }

    private boolean EstaEnLista(ArrayList<aeArco> lista, int pto) {
        for(int i=0; i<lista.size(); i++)
            if (lista.get(i).x == pto)
                return true;
        return false;
    }

    public ArrayList<beUbicacion> getOrdenOptimoUbics() {
        return this.ordenOptimoUbics;
    }

    public ArrayList<aePuntoUbicacion> getPuntosRutaOptima() {
        return this.puntosRutaOptima;
    }

    private void ubicarNodosObligatorios(ArrayList<beUbicacion> ubicaciones) {
        aePuntoUbicacion pto = null;
        for(int i=0;i<ubicaciones.size();i++){
            pto = new aePuntoUbicacion();
            pto.setIdUbicacion(ubicaciones.get(i).getIdUbicacion());
            pto.setOrden(i);
            pto.setCoorX(ubicaciones.get(i).getCoordenadas().getxEnMapa());
            pto.setCoorY(ubicaciones.get(i).getCoordenadas().getyEnMapa());
            this.obligatorios.add(pto);
        }
    }

    private void ubicarNodosTransitorios(int posEntX, int posEntY) throws Exception{
        aePuntoUbicacion pto = null;
        int ordenIni = this.obligatorios.size();
        blHelper blh = new blHelper();
        boolean dispArriba = false;
        boolean dispAbajo = false;
        boolean dispDerecha = false;
        boolean dispIzquierda = false;
        beAlmacen datosAlmacen = blh.obtenerDatosAlmacen();
        int numCol = blh.calcularNumeroColumnas(datosAlmacen.getRacksXFila(),datosAlmacen.getUbsxrack());
        int numFil = blh.calcularNumeroFilas(datosAlmacen.getFilas());
        char [][]matrizAlmacen = (new blHelper()).obtenerMatrizAlmacen(numCol, numFil, datosAlmacen.getUbsxrack());
        for(int i=0;i<numFil;i++){
            for(int j=0;j<numCol;j++){
                if (matrizAlmacen[j][i] == ' '){
                    if (j!=posEntX || i!=posEntY){
                        if (j==0)
                            dispIzquierda = false;
                        else{
                            if (matrizAlmacen[j-1][i] == '*')
                                dispIzquierda = false;
                            else
                                dispIzquierda = true;
                        }
                        if (j==(numCol-1))
                            dispDerecha = false;
                        else{
                            if (matrizAlmacen[j+1][i] == '*')
                                dispDerecha = false;
                            else
                                dispDerecha = true;
                        }
                        if (i==0)
                            dispArriba = false;
                        else{
                            if (matrizAlmacen[j][i-1] == '*')
                                dispArriba = false;
                            else
                                dispArriba = true;
                        }
                        if (i==(numFil-1))
                            dispAbajo = false;
                        else{
                            if (matrizAlmacen[j][i+1] == '*')
                                dispAbajo = false;
                            else
                                dispAbajo = true;
                        }

                        int numVerdades = this.numeroVerdaderos(dispAbajo,dispArriba,dispIzquierda,dispDerecha);
                        if ((numVerdades == 4)||(numVerdades == 3)){
                            pto = new aePuntoUbicacion();
                            pto.setCoorX(j);
                            pto.setCoorY(i);
                            pto.setOrden(ordenIni);
                            this.transitorios.add(pto);
                            ++ordenIni;
                        }
                        if (numVerdades == 2){
                            if (!((dispDerecha && dispIzquierda)||(dispArriba && dispAbajo))){
                                pto = new aePuntoUbicacion();
                                pto.setCoorX(j);
                                pto.setCoorY(i);
                                pto.setOrden(ordenIni);
                                this.transitorios.add(pto);
                                ++ordenIni;
                            }
                        }
                        if (numVerdades == 1){
                            pto = new aePuntoUbicacion();
                            pto.setCoorX(j);
                            pto.setCoorY(i);
                            pto.setOrden(ordenIni);
                            this.transitorios.add(pto);
                            ++ordenIni;
                        }
                    }
                }
            }
        }
    }

    private int numeroVerdaderos(boolean dispAbajo, boolean dispArriba, boolean dispIzquierda, boolean dispDerecha) {
        int cont = 0;
        if (dispAbajo)
            ++cont;
        if (dispArriba)
            ++cont;
        if (dispIzquierda)
            ++cont;
        if (dispDerecha)
            ++cont;
        return cont;
    }

    private void calcularMatrizNodos() {
        this.tamanhoLadoArco = this.obligatorios.size()+this.transitorios.size();
        this.matrizArcos = new int[this.tamanhoLadoArco][this.tamanhoLadoArco];
        this.inicializarMatrizArcos();
        this.ingresarArcos();
        this.mostrarMatriz();
    }

    private void inicializarMatrizArcos() {
        for(int i=0;i<this.tamanhoLadoArco; i++)
            for(int j=0; j<this.tamanhoLadoArco; j++)
                this.matrizArcos[j][i] = -1;
    }

    private void mostrarMatriz(){
//        for(int i=0; i<this.tamanhoLadoArco; i++){
//            for(int j=0; j<this.tamanhoLadoArco; j++){
//                if (j==0)
//                    System.out.print(""+this.matrizArcos[j][i]);
//                else
//                    System.out.print("\t"+this.matrizArcos[j][i]);
//            }
//            System.out.println("");
//        }
    }

    private void ingresarArcos() {
        aePuntoUbicacion p1 = null;
        aePuntoUbicacion p2 = null;
        for(int fil=(this.tamanhoLadoArco-1); fil>=0; fil--){
            for(int col=0; col<(this.tamanhoLadoArco-fil); col++){
                if (col!=(this.tamanhoLadoArco-fil-1)){
                    p1 = this.buscarPuntoPorOrden(col);
                    p2 = this.buscarPuntoPorOrden(this.tamanhoLadoArco-fil-1);
                    if (!((p1.getCoorX() == p2.getCoorX())&&(p1.getCoorY()==p2.getCoorY()))){
                        if (p1.getCoorX() == p2.getCoorX()){
//                            if (!(p1.getOrden()<this.obligatorios.size() || p2.getOrden()<this.obligatorios.size()||(col==0))){
//                                matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorY()-p2.getCoorY());
//                                matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorY()-p2.getCoorY());
//                            }
//                            else{
                            //NO ESTOY CONSIDERANDO CUANDO LA ENTRADA SE UNE CON UN NODO TRANSITORIO
                                if (!((p1.getOrden()<this.obligatorios.size() && p1.getOrden()>0) || (p2.getOrden()<this.obligatorios.size() && p2.getOrden()>0))&&((col==0)||((p1.getOrden()>=this.obligatorios.size())&&(p2.getOrden()>=this.obligatorios.size())))){
                                    matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorY()-p2.getCoorY());
                                    matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorY()-p2.getCoorY());
                                }
//                                else{
//                                    if (((((p1.getCoorY()-1) % 3)==0)&&(p2.getCoorY() == (p1.getCoorY()+2)))||((((p2.getCoorY()-1) % 3)==0)&&(p1.getCoorY() == (p2.getCoorY()+2)))){
//                                        matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorY()-p2.getCoorY());
//                                        matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorY()-p2.getCoorY());
//                                    }
//                                }
//                            }
                        }
                        if ((p1.getCoorY() == p2.getCoorY())){
                            if ((col==0) && !(p2.getOrden()<this.obligatorios.size())){
                                matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorX()-p2.getCoorX());
                            }
                            if ((col!=0)&&(p2.getOrden()<this.obligatorios.size())&&(p1.getOrden()<this.obligatorios.size())){
                                matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorX()-p2.getCoorX());
                            }
                        }
                        if (((p1.getCoorY()-1) == p2.getCoorY())||(p1.getCoorY() == (p2.getCoorY()-1))){
                            if (col==0){
                                if ((((p1.getCoorY()-1) % 3)==0) && (p2.getOrden() < this.obligatorios.size())){
                                    matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                    matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                }
                                //AGREGUÉ ESTO PARA SOLUCIONAR EL PROBLEMA CON CESAR
                                else{
                                    if ((((p2.getCoorY()-1) % 3)==0) && (p1.getOrden() < this.obligatorios.size())){
                                        matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                        matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                    }
                                }
                            }
                            else{
                                if (!(p1.getOrden()<this.obligatorios.size() && p2.getOrden()<this.obligatorios.size())){
                                    matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                    matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                }
                            }
                        }
                        if (((p1.getCoorY()-2) == p2.getCoorY())||(p1.getCoorY() == (p2.getCoorY()-2))){
                            if ((p1.getOrden()<this.obligatorios.size()) && (p2.getOrden()<this.obligatorios.size()) && (p1.getOrden()>0) && (p2.getOrden()>0)){
                                if ((((p1.getCoorY() % 3)==0)&&(p2.getCoorY() == (p1.getCoorY()+2)))||(((p2.getCoorY() % 3)==0)&&(p1.getCoorY() == (p2.getCoorY()+2)))){
                                    matrizArcos[col][this.tamanhoLadoArco-fil-1] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                    matrizArcos[this.tamanhoLadoArco-fil-1][col] = Math.abs(p1.getCoorX()-p2.getCoorX());
                                }
                            }
                        }
                    }
                    else{
                        matrizArcos[col][this.tamanhoLadoArco-fil-1] = 0;
                        matrizArcos[this.tamanhoLadoArco-fil-1][col] = 0;
                    }
                }
            }
        }
    }

    private aePuntoUbicacion buscarPuntoPorOrden(int orden){
        for(int i=0; i<this.obligatorios.size(); i++){
            if (this.obligatorios.get(i).getOrden() == orden)
                return this.obligatorios.get(i);
        }
        for(int i=0; i<this.transitorios.size(); i++){
            if (this.transitorios.get(i).getOrden() == orden)
                return this.transitorios.get(i);
        }
        return null;
    }
}
